﻿using System;
using System.Collections;
using System.Text;

namespace mfLogger
{
    public class mfLogger : ILoggerAppender
    {
        #region Consts & Fields
        internal const int C_INT_INITIAL_MESSAGE_MAX_COUNT = 10;

        static object _sync = new object();
        #endregion

        #region CTOR// Singleton
        //http://msdn.microsoft.com/en-us/library/ff650316.aspx
        //--> not thread-safe, with static initialization

        private static readonly mfLogger _instance = new mfLogger();

        private mfLogger()
        {
            Name = this.GetType().Name;

            Appenders = new mfAppenderCollection();
            Messages = new mfLogMessageCollection(_msgCapacity);

            _level = enumLogMessageLevel.Info;
        }

        public static mfLogger Instance
        {
            get
            {
                return _instance;
            }
        }

        #endregion

        #region Properties
        int _msgCapacity = C_INT_INITIAL_MESSAGE_MAX_COUNT;
        public int MessageCapacity
        {
            get
            {
                return _msgCapacity;
            }
            set
            {
                Messages.Clear();
                Messages.Capacity = value;

                _msgCapacity = value;
            }
        }

        public mfAppenderCollection Appenders { get; private set; }

        /// <summary>
        /// contains an always by date sorted log message list
        /// </summary>
        public mfLogMessageCollection Messages { get; private set; }

        #endregion

        #region ILogger

        public string Name
        {
            get;
            set;
        }

        bool _isEnabled = true;
        public bool IsEnabled
        {
            get
            {
                return _isEnabled;
            }
            set
            {
                foreach (ILoggerAppender appender in Appenders)
                {
                    appender.IsEnabled = value;
                }

                _isEnabled = value;
            }
        }

        enumLogMessageLevel _level;
        /// <summary>
        /// trace-level used for central message cache
        /// </summary>
        public enumLogMessageLevel Level
        {
            get
            {
                return _level;
            }
            set
            {
                foreach (ILoggerAppender appender in Appenders)
                {
                    appender.Level = value;
                }

                for (int i = 0; i < Messages.Count; i++)
                {
                    if (Messages[i].Level < value)
                    {
                        mfLogMessage msg = Messages[i] as mfLogMessage;

                        Messages.RemoveAt(i);
                        if (msg != null) msg.Dispose();
                    }
                }

                _level = value;
            }
        }

        public void Log(mfLogMessage msg)
        {
            HandleMessage(msg);
        }

        public void Debug(string text)
        {
            HandleMessage(new mfLogMessage(enumLogMessageLevel.Debug, text));
        }
        public void Info(string text)
        {
            HandleMessage(new mfLogMessage(text));
        }

        public void Warning(string text)
        {
            HandleMessage(new mfLogMessage(enumLogMessageLevel.Warning, text));
        }

        public void Error(Exception ex)
        {
            HandleMessage(new mfLogMessage(ex));
        }

        public void Error(string text)
        {
            HandleMessage(new mfLogMessage(enumLogMessageLevel.Error, text));
        }

        public void HandleMessage(mfLogMessage msg)
        {
            if (msg.Level >= Level)
            {
                Messages.Add(msg);
            }

            //forward received message to appenders
            foreach (ILoggerAppender logger in Appenders)
            {
                logger.HandleMessage(msg);
            }
        }
        #endregion

    }
}
